package com.citycloud.ccuap.tc.oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;

import com.citycloud.ccuap.tc.oauth2.config.handler.CustomerAccessDeniedHandler;
import com.citycloud.ccuap.tc.oauth2.config.handler.CustomerAuthenticationEntryPoint;
import com.citycloud.ccuap.tc.oauth2.config.handler.CustomerAuthenticationFailureHandler;
import com.citycloud.ccuap.tc.oauth2.config.handler.CustomerAuthenticationSuccessHandler;
import com.citycloud.ccuap.tc.oauth2.config.handler.CustomerLogoutSuccessHandler;

/**
 * Spring Security 安全配置
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final CustomerAuthenticationEntryPoint authenticationEntryPoint;
    private final CustomerAccessDeniedHandler accessDeniedHandler;
    private final CustomerAuthenticationSuccessHandler successHandler;
    private final CustomerAuthenticationFailureHandler failureHandler;
    private final UserDetailsService userDetailsService;
    private final CustomerLogoutSuccessHandler logoutSuccessHandler;

    @Autowired
    public WebSecurityConfiguration(
            CustomerAuthenticationEntryPoint authenticationEntryPoint,
            CustomerAccessDeniedHandler accessDeniedHandler,
            CustomerAuthenticationSuccessHandler successHandler,
            CustomerAuthenticationFailureHandler failureHandler,
            UserDetailsService userDetailsService,
            CustomerLogoutSuccessHandler logoutSuccessHandler
    ) {
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.accessDeniedHandler = accessDeniedHandler;
        this.successHandler = successHandler;
        this.failureHandler = failureHandler;
        this.userDetailsService = userDetailsService;
        this.logoutSuccessHandler = logoutSuccessHandler;
    }

    /**需要配置这个 bean 来支持 OAuth2 的密码授权模式（password grant type）*/
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**设置默认的加密方式*/
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    public static void main(String[] args) { /*加密方式测试*/
        System.out.println(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("888888"));
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        MyAuthenticationProvider provider = new MyAuthenticationProvider();
        provider.setHideUserNotFoundExceptions(false);
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder());
        auth.authenticationProvider(provider);
    }

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/oauth/check_token", "/static/**");

        //Open API
        web.ignoring().antMatchers("/user/getUserInfo", "/nonSessionBased/**");


    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint);

        http.csrf().disable();

        //登陆配置
        http.formLogin().loginProcessingUrl("/login")
                // 自定义处理登录成功后的处理器
                .successHandler(successHandler)
                .failureHandler(failureHandler);

        http.logout()
                .logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies("JSESSIONID");

        http.authorizeRequests().anyRequest()/*所有请求*/.authenticated();/*都需要认证*/
    }
}
